package donnees;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class FabriqueCommande {

	public static FabriqueCommande fc = null;
	private Map<Integer, Commande> cache;
	Connection dbCon;
	PreparedStatement creer;
	PreparedStatement rechercherCommande;
	PreparedStatement rechercherLesIdCommandeClient;
	PreparedStatement rechercherLesIdLignesCommande;
	PreparedStatement updaterCommande;
	PreparedStatement recupererDernierID;

	public static FabriqueCommande getInstance() throws SQLException {
		if (fc == null) {
			fc = new FabriqueCommande();
		}
		return fc;
	}

	private FabriqueCommande() throws SQLException {
		this.cache = new HashMap<Integer, Commande>();
		this.initConnection();
	}

	private void initConnection() throws SQLException {
		this.dbCon = DB.getInstance().getConnection();

		this.creer = dbCon
				.prepareStatement("INSERT INTO Commande(idCommande,prixtotal,datecommande,datelivraison,client_idclient, etat) VALUES(NEXT VALUE FOR Commande_seq,?,?,?,?,?)");

		this.rechercherCommande = dbCon
				.prepareStatement("SELECT idCommande,prixtotal,datecommande,datelivraison,client_idclient,etat FROM Commande WHERE idCommande=?");

		this.rechercherLesIdCommandeClient = dbCon
				.prepareStatement("SELECT idCommande FROM commande WHERE client_idclient = ?");

		this.rechercherLesIdLignesCommande = dbCon
				.prepareStatement("SELECT idlignecommande FROM lignecommande WHERE idcommande=?");

		this.updaterCommande = dbCon
				.prepareStatement("UPDATE Commande SET prixtotal = ?, datelivraison = ?, etat = ? WHERE idCommande=?");

		// IDENTITY uniquement pour des colonnes identity et non les sequence
		// Pas non plus de fonction pour récupérer dernière valeur d'une sqce
		// dans hsqldb ...
		//this.recupererDernierID = dbCon.prepareStatement("CALL IDENTITY()");

		this.recupererDernierID = dbCon
				.prepareStatement("SELECT max(idcommande) FROM commande");
	}

	/* creer */
	public Commande creer(Double prixtotal, Date datecommande,
			Date datelivraison, int idClient, int etat) throws SQLException {
		// tester les données
		boolean flag = true;
		if (prixtotal < 0.0) {
			flag = false;
		}

		// insérer le nouveau Commande
		if (flag) {
			creer.clearParameters();
			creer.setDouble(1, prixtotal);
			creer.setDate(2, datecommande);
			creer.setDate(3, datelivraison);
			creer.setInt(4, idClient);
			creer.setInt(5, etat);
			creer.executeUpdate();
			// récupérer son id et créer un objet Commande à retourner
			ResultSet retour = recupererDernierID.executeQuery();
			retour.next();

			Commande laCommande = new Commande(retour.getInt(1), prixtotal,
					datecommande, datelivraison, null, idClient, etat);
			cache.put(retour.getInt(1), laCommande);
			return laCommande;
		} else {
			return null;
		}

	}

	/* rechercher */
	public Commande rechercher(Integer idCommande) throws SQLException {
		
		if (cache.containsKey(idCommande)) {
			return cache.get(idCommande);
		} else {
			rechercherCommande.clearParameters();
			rechercherCommande.setInt(1, idCommande);
			ResultSet retour = rechercherCommande.executeQuery();
			if (retour.next()) {
				Commande laCommande = new Commande(idCommande,
						retour.getDouble(2), retour.getDate(3),
						retour.getDate(4),
						this.getLesIdLignesCommande(idCommande), new Integer(
								retour.getInt(5)),
						new Integer(retour.getInt(6)));
				cache.put(idCommande, laCommande);
				return laCommande;
			}
			return null;
		}
	}

	/* rechercher commandes d'un client */
	public List<Integer> rechercherIdCommandesCLient(Integer idClient)
			throws SQLException {
		
		List<Integer> lesId = new ArrayList<Integer>();
		rechercherLesIdCommandeClient.setInt(1, idClient);
		ResultSet retour = rechercherLesIdCommandeClient.executeQuery();
		while (retour.next()) {
			lesId.add(retour.getInt(1));
		}
		return lesId;
	}

	/* mettre à jour */
	public void update(Integer idCommande, Double prixtotal, Date livraison,
			Integer etat) throws SQLException {

		boolean flag = true;

		if (prixtotal < 0)
			flag = false;

		if (flag) {
			updaterCommande.clearParameters();
			updaterCommande.setDouble(1, prixtotal);
			updaterCommande.setDate(2, livraison);
			updaterCommande.setInt(3, etat);
			updaterCommande.setInt(4, idCommande);

			// update db
			updaterCommande.executeUpdate();

			// update cache
			deleteFromCache(idCommande);
			Commande cmd = rechercher(idCommande);
			cache.put(idCommande, cmd);

		}
	}

	// viderCache
	public void flushCache() {
		this.cache.clear();
	}
	
	public void deleteFromCache(Integer idCommande) {
		this.cache.remove(idCommande);
	}
	
	

	public List<Integer> getLesIdLignesCommande(Integer idCommande)
			throws SQLException {
		List<Integer> lesId = new ArrayList<Integer>();
		rechercherLesIdLignesCommande.setInt(1, idCommande);
		ResultSet retour = rechercherLesIdLignesCommande.executeQuery();
		while (retour.next()) {
			lesId.add(retour.getInt(1));
		}
		return lesId;
	}
}
